#include<linux/module.h>
#include <linux/init.h>
#include<linux/slab.h>
#include<linux/kernel.h>
#include<linux/input.h>
#include <linux/fs.h>
#include <linux/dbg_tool.h>
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include "input_debug.h"

struct pm_debug {
	struct device dev;
	struct work_struct	work_q;
};
struct pm_debug *pm_st;
static ssize_t show_name(struct device *pdev, struct device_attribute *attr, char *buf)
{
	return 0;
}

static ssize_t store_name(struct device *pdev, struct device_attribute *attr,
					const char *buf, size_t size)
{
	return 0;
}

DEVICE_ATTR(vir_event, S_IWUGO | S_IRUGO, show_name, store_name);

#if 0
struct bus_type usb_bus_type = {
	.name =		"usb",
	.match =	usb_device_match,
	.uevent =	usb_uevent,
};
static const struct dev_pm_ops usb_device_pm_ops = {
	.prepare =	usb_dev_prepare,
	.complete =	usb_dev_complete,
	.suspend =	usb_dev_suspend,
	.resume =	usb_dev_resume,
	.freeze =	usb_dev_freeze,
	.thaw =		usb_dev_thaw,
	.poweroff =	usb_dev_poweroff,
	.restore =	usb_dev_restore,
#ifdef CONFIG_USB_SUSPEND
	.runtime_suspend =	usb_runtime_suspend,
	.runtime_resume =	usb_runtime_resume,
	.runtime_idle =		usb_runtime_idle,
#endif
};
#endif

int pm_dbg_runtime_suspend(struct device *dev)
{
	TL_DBG("zoucao %s\n", __func__);
	return 0;
}

int	pm_dbg_runtime_resume(struct device *dev)
{
	TL_DBG("zoucao %s\n", __func__);
	return 0;
}

int pm_dbg_runtime_idle(struct device *dev)
{
	TL_DBG("zoucao %s\n", __func__);
	return 0;
}

int pm_dbg_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	TL_DBG("zoucao %s\n", __func__);
	return 0;
}

char *pm_dbg_devnode(struct device *dev, umode_t *mode)
{
	TL_DBG("zoucao %s\n", __func__);
	return kasprintf(GFP_KERNEL, "pm_dbg");
}

void pm_dbg_release_dev(struct device *dev)
{
	TL_DBG("zoucao %s\n", __func__);
	return ;
}

static const struct dev_pm_ops pm_dbg_device_pm_ops = {
	//.prepare =	usb_dev_prepare,
	//.complete =	usb_dev_complete,
	.suspend =	usb_dev_suspend,
	.resume =	usb_dev_resume,
	//.freeze =	usb_dev_freeze,
	//.thaw =		usb_dev_thaw,
	//.poweroff =	usb_dev_poweroff,
	//.restore =	usb_dev_restore,
#ifdef CONFIG_PM
	.runtime_suspend =	pm_dbg_runtime_suspend,
	.runtime_resume	 =	pm_dbg_runtime_resume,
	.runtime_idle    =	pm_dbg_runtime_idle,
#endif
};

struct device_type pm_dbg_device_type = {
	.name =		"pm_dbg_device",
	.release =	pm_dbg_release_dev,
	.uevent =	pm_dbg_dev_uevent,
	.devnode = 	pm_dbg_devnode,
#ifdef CONFIG_PM
	.pm =		&pm_dbg_device_pm_ops,
#endif
};

int input_dbg_entry(void)
{
	struct device *dev;
	int ret;

	pm_st = kzalloc(sizeof(struct pm_debug) ,GFP_KERNEL);
	if(!pm_st)
	  return -ENOMEM;
	dev = &pm_st->dev;
		
	device_initialize(dev);
	dev->init_name = "pm_debug";
	dev->type	= &pm_dbg_device_type; 
	dev->parent = NULL;
	dev->bus = NULL;
	dev->groups = NULL;
	ret = device_add(dev);
	if(ret)
		return -ENODEV;
	get_device(dev);

	ret= device_create_file(dev, &dev_attr_vir_event);
	
	device_set_wakeup_enable(dev, true);
	pm_runtime_disable(dev);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);
	pm_runtime_allow(dev);
	//pm_runtime_set_autosuspend_delay(dev ,100);
	//ret	= pm_request_autosuspend(dev);
	//ret = pm_runtime_resume(dev);
	pm_runtime_get_sync(dev);
	TL_DBG("zoucao usage_count:%d dispatch:%d \n"
			,atomic_read(&dev->power.usage_count)
			,dev->power.disable_depth	
			);
	TL_DBG("zoucao ret:%d\n" ,ret);

	TL_DBG("zoucao %s\n", __func__);
	return 0;
}

void input_dbg_exit(void)
{
	TL_DBG("zoucao %s\n", __func__);
	device_del(&pm_st->dev);
	kfree(pm_st);
}

module_init(input_dbg_entry);
module_exit(input_dbg_exit);
MODULE_AUTHOR("Iiro Valkonen");
MODULE_DESCRIPTION("Driver for Atmel maXTouch Touchscreen Controller");
MODULE_LICENSE("GPL");
